class_name MediaListItem
extends PanelContainer

const COLOR_NORMAL := Color(0.22, 0.21, 0.25, 1)
const COLOR_HOVERED := Color(0.09, 0.09, 0.09, 1)
const COLOR_PRESSED := Color(0.5, 0.5, 0.5, 1)
const SIZE := Vector2(220, 260)
const THUMBNAIL_RATIO: float = 16.0 / 9.0

export(String, FILE) var default_thumbnail_path: String = "res://icon.png"
export(PackedScene) var ChannelCard_scene: PackedScene = load("res://src/scenes/channel_card/channel_card.tscn")

# URL to get the media through the LBRY protocol
var _lbry_url: String
# URL of the channel on the LBRY blockchain
var _channel_url: String
# URL to get the media from the locally run HTTP server
var _streaming_url: String
# mime-type of the media
var _mime_type: String
# All the resolved data for this `_lbry_url`
var _data: Dictionary = {}
var _initialized: bool = false
# Has this node finished retrieving its data
var _is_setup: bool = false
var _replace_with_placeholder: bool = true
var _default_thumbnail_img: Image = load(default_thumbnail_path).get_data()
var _async_helper := AsyncHelper.new(self)
onready var _thumbnail_spinner_node: Spinner = find_node("ThumbnailSpinner")
onready var _media_thumbnail_node: TextureRect = find_node("MediaThumbnail")
onready var _title_node: Label = find_node("Title")
onready var _channel_card_node: ChannelCard = find_node("ChannelCard")


func _ready() -> void:
	_setup()


func init(data: Dictionary) -> void:
	if _initialized:
		return
	
	_data = data
	_lbry_url = _data.get("short_url", "")
	_channel_url = _data \
		.get("signing_channel", {}) \
		.get("short_url", "")
	_initialized = true


func is_setup() -> bool:
	"""
	Returns:
		If the node has finished setting up
	"""
	return _is_setup


func set_title(text: String) -> void:
	$VBoxContainer/MediaContainer/VBoxContainer/Title.set_text(text)
	$VBoxContainer/MediaContainer/VBoxContainer/Title.set_tooltip(text)


func set_media_thumbnail(image: Image) -> void:
	var media_thumbnail := ImageTexture.new()
	if image.is_empty():
		image = _default_thumbnail_img
	_stretch_image_to_ratio(image, THUMBNAIL_RATIO)
	media_thumbnail.create_from_image(image)
	_media_thumbnail_node.set_texture(media_thumbnail)
	_media_thumbnail_node.show()
	_thumbnail_spinner_node.hide()


func set_lbry_url(url: String) -> void:
	_lbry_url = url


func connect_media_button(sig: String, target: Object, method: String,
		binds: Array=[], flags: int=0) -> int:
	var err: int = $VBoxContainer/MediaContainer.connect(
			sig, target, method, binds, flags)
	return err


func connect_channel_button(sig: String, target: Object, method: String,
		binds: Array=[], flags: int=0) -> int:
	var err: int = $VBoxContainer/ChannelContainer.connect(
			sig, target, method, binds, flags)
	return err


func is_media_button_connected(sig: String, target: Object, method: String
		) -> bool:
	return $VBoxContainer/MediaContainer.is_connected(sig, target, method)


func is_channel_button_connected(sig: String, target: Object, method: String
		) -> bool:
	return $VBoxContainer/ChannelContainer.is_connected(sig, target, method)


func set_media_button_visible(visibility: bool) -> void:
	$VBoxContainer/MediaContainer.set_visible(visibility)
	$VBoxContainer/MediaContainer.set_disabled(not visibility)


func set_channel_button_visible(visiblity: bool) -> void:
	$VBoxContainer/ChannelContainer.set_visible(visiblity)
	$VBoxContainer/ChannelContainer.set_disabled(not visiblity)


func set_media_button_disabled(disabled: bool) -> void:
	$VBoxContainer/MediaContainer.set_disabled(disabled)


func set_channel_button_disabled(disabled: bool) -> void:
	$VBoxContainer/ChannelContainer.set_disabled(disabled)


func _setup() -> void:
	if len(_data) == 0:
		return
	
	set_custom_minimum_size(SIZE)
	
	var claim_data: Dictionary = _data
	if _data.has("reposted_claim"):
		# Data about a repost is found under the "reposted_claim" key,
		# everything within that is structured the same as a normal post
		claim_data = _data["reposted_claim"]
	
	var title: String = claim_data.get("value", {}).get("title", "")
	set_title(title)
	
	var media_thumbnail_url: String = claim_data \
			.get("value", {}) \
			.get("thumbnail", {}) \
			.get("url", "")
	var tracker: Dictionary = _async_helper.connect_wrapped(
			Requests.get_image(media_thumbnail_url), "completed")
	yield(_async_helper.wait_until_finished([tracker]), "completed")
	var media_thumbnail_img: Image = tracker["result"]
	set_media_thumbnail(media_thumbnail_img)
	_media_thumbnail_node.set_tooltip(_lbry_url)
	
	var channel_card: ChannelCard = ChannelCard_scene.instance()
	channel_card.init(_channel_url)
	_channel_card_node.get_parent().add_child_below_node(
			_channel_card_node, channel_card)
	_channel_card_node.queue_free()
	_channel_card_node = channel_card
	
	_is_setup = true


func _stretch_image_to_ratio(image: Image, ratio: float) -> void:
	"""
	Stretches the image so that the ratio of its width divided by its height
	match that of `ratio`. The image is always stretched so that it gets bigger
	
	Args:
		image: the image to stretch
		ratio: the ratio of the resulting images width divided by its height.
			If you want to stretch the image to have an aspect ratio of 16:9
			then you would pass `16 / 9` as the argument
	"""
	var current_ratio: float = image.get_size().x / image.get_size().y
	if current_ratio < ratio:
		var new_width := int(image.get_height() * ratio)
		image.resize(new_width, image.get_height())
	elif current_ratio > ratio:
		var new_height := int(image.get_width() / ratio)
		image.resize(image.get_width(), new_height)
